<template>
  <a-select
    v-model:value="selectValue"
    :placeholder="placeholder"
    :disabled="disabled"
    :readonly="readonly"
    :show-search="showSearch"
    @change="handleSelectChange"
    :options="options"
    :field-names="{ label: labelField, value: valueField }"
    :filter-option="handleFilterOption"
    allowClear
  >
    <template #suffixIcon v-if="loading">
      <LoadingOutlined spin />
    </template>
    <template #notFoundContent v-if="loading">
      <span>
        <LoadingOutlined spin class="mr-1" />
        请等待数据加载完成...
      </span>
    </template>
  </a-select>
</template>
<script lang="ts" setup>
  import { ref, inject, watch, onMounted } from 'vue';
  import { isFunction } from '/@/utils/is';
  import { LoadingOutlined } from '@ant-design/icons-vue';
  import { getDatasourceData } from '/@/api/system/datasource';
  import { getDicDetailList } from '/@/api/system/dic';
  import { camelCaseString, apiConfigFunc } from '/@/utils/event/design';

  const props = defineProps({
    placeholder: { type: String },
    value: { type: [String, Number] },
    labelField: { type: String },
    valueField: { type: String },
    showSearch: { type: Boolean },
    disabled: { type: Boolean },
    readonly: { type: Boolean },
    params: {
      type: [Array, Object, String, Number],
    },
    immediate: {
      type: Boolean,
      default: true,
    },
    dataSourceOptions: { type: Array },
    dicOptions: { type: Array },
    //数据来源 默认为空  如果不为空 则参数 api
    datasourceType: String,
    api: {
      type: Function as PropType<(arg?: Recordable) => Promise<any[]>>,
      default: null,
    },
    apiConfig: Object,
    mainKey: String,
    index: Number,
  });
  const selectValue = ref<string | number | undefined>(undefined);
  const loading = ref(false);
  const options = ref<any[]>([]);
  const formModel = inject<any>('formModel', null);
  const isCustomForm = inject<boolean>('isCustomForm', false);
  const emit = defineEmits(['update:value', 'change']);
  onMounted(async () => {
    if (props.value && props.datasourceType === 'dic') {
      await getOptions();
      changeData(props.value);
    }
  });
  watch(
    () => props.value,
    (val) => {
      selectValue.value = val || undefined;
    },
    {
      immediate: true,
    },
  );

  const handleFilterOption = (input: string, option) => {
    const label = option.label || option.name;
    return label.toLowerCase().includes(input.toLowerCase());
  };

  const handleSelectChange = (value) => {
    emit('update:value', value);
    emit('change', value);
    selectValue.value = props.value === undefined ? value : props.value;
    changeData(value);
  };
  function changeData(value) {
    let assoConfig =
      props.datasourceType === 'dic' ? props.dicOptions : props.apiConfig?.outputParams;
    if (!formModel) return;
    assoConfig?.map((item: any) => {
      if (item.bindField) {
        const index = options.value.findIndex((opt) => {
          return opt[props.valueField!] === value;
        });
        if (isCustomForm) {
          if (props.mainKey) {
            formModel[props.mainKey][props.index!][item.bindField!] =
              index === -1 ? '' : options.value[index][item.name];
          } else {
            formModel[item.bindField!] = index === -1 ? '' : options.value[index][item.name];
          }
        } else {
          if (props.mainKey) {
            formModel[props.mainKey][props.index!][camelCaseString(item.bindField)!] =
              index === -1 ? '' : options.value[index][item.name];
          } else {
            formModel[camelCaseString(item.bindField)!] =
              index === -1 ? '' : options.value[index][item.name];
          }
        }
      }
    });
  }
  const getOptions = async () => {
    let api;
    if (props.datasourceType) {
      if (props.datasourceType === 'dic') {
        api = getDicDetailList;
      } else if (props.datasourceType === 'datasource') {
        api = getDatasourceData;
      } else if (props.datasourceType === 'api' && props.apiConfig?.path) {
        options.value = await apiConfigFunc(props.apiConfig, isCustomForm, formModel);
        return;
      }
    } else {
      api = props.api;
    }
    options.value = [];
    if (!api || !isFunction(api)) return;
    try {
      if (!props.params) return;
      loading.value = true;
      const res = await api(props.params);

      if (Array.isArray(res)) {
        options.value = res;
        return;
      }
    } catch (error) {
      console.warn(error);
    } finally {
      loading.value = false;
    }
  };

  watch(
    () => [props.params, props.apiConfig],
    () => {
      getOptions();
    },
    {
      immediate: true,
      deep: true,
    },
  );
  watch(
    () => props.datasourceType,
    (curVal, oldVal) => {
      getOptions();
      if (!props.value || (curVal !== oldVal && !!oldVal)) selectValue.value = undefined;
    },
  );
</script>
